\ a simple compiler to allow us to write bytecode in a totally implentation-blind way.

\ here's what it will take care of for us:

\ [x] 8-bit instruction mode
\ [x] control flow (IF,THEN)
\ [x] automatic literal width detection
\ [x] automatic discerning between primitives and subroutines
\ [ ] interactive testing via native compilation mode (taking advantage of the fully Forth-compatible syntax)
\ [x] define zp variables (8bit,16bit,more) - basic
\ [x] define wram variables and random addresses - basic
\ [ ] convert punctuation to assembler-legal text

\ todo
\ [ ] alit
\ [ ] literal vpstore




\ File Output personality

0 value #1

: fileout-invoke ;
: fileout-revoke ;
: fileout-/input ;
: fileout-type     #1 write-file throw ;
: fileout-emit     pocket c! pocket 1 fileout-type ;
: fileout-?type    ?dup if #1 write-file throw else drop then ;
: fileout-cr       13 fileout-emit 10 fileout-emit ;
: fileout-page   fileout-cr fileout-cr " ------------------------------------------------------------------------------------ " fileout-type fileout-cr ;
: fileout-attribute drop ;


create fileout-personality
	4 cells ,
	9 ,
	0 ,
	0 ,
	' fileout-invoke ,
	' fileout-revoke ,
	' fileout-/input ,
	' fileout-emit ,
	' fileout-type ,
	' fileout-?type ,
	' fileout-cr ,
	' fileout-page ,
	' fileout-attribute ,






variable pc

wordlist constant bytecode   \ contains all the primitives and redefined words

defer output

: ide-output  cr type ;
: file-output   fileout-cr  fileout-?type ;

' ide-output is output


: opcode   "    .db " <$ $+ $> output   1 pc +! ;

: prim   ( "targetname" -- name )
	create does> body> >name count opcode ;




\ TBD


only forth definitions bytecode +order definitions

	prim end
	prim fetch
	prim store
	prim plusstore
	prim alit
	prim plus
	prim sbtrkt
	prim invert
	prim negate
	prim vpstore
	prim vstore
	prim oneplus
	prim oneminus
	prim twodiv
	prim twomul
	prim fetchplus
	prim storeplus
	prim fetcha
	prim storea
	prim zless
	prim less
	prim zgreater
	prim greater
	prim uless
	prim ugreater
	prim equals

	prim lit
	prim twolit
	prim call
	prim exit


	: db "    .db " <$ bl parse $+ $> output 1 pc +! ;
	: dw "    .dw " <$ bl parse $+ $> output 2 pc +! ;

	: c,   "    .db $" <$ hex (.) decimal $+ $> output  1 pc +! ;
	: w,   "    .dw $" <$ hex (.) decimal $+ $> output  2 pc +! ;


	: (#)   bl word count dup >r
		    evaluate ( n )
		    dup abs 256 < if
		    	r> ( length ) 4 < if lit c, else twolit w, then
		    else
				r> drop   twolit dw
		    then ;

	: (:)   >in @   bl word count <$ " :" $+ $> output
	      >in !   create does>  call  "    .dw " <$ body> >name count $+ $> output   2 pc +! ;
	: (;)   exit ;

	: label
		bl parse <$ " :" $+ $> output ;

	: entry
		label   "    jsr bytecode" output   3 pc +! ;


	: b:   lit  "    .db " <$ bl parse $+ $> output  1 pc +! ;
	: w:   twolit "    .dw " <$ bl parse $+ $> output  2 pc +! ;

	\ these are special cases
\	[x] iff
\	[x] mif
\	[ ] for
\	[ ] next
\	[ ] branch
\	[ ] while

	variable nest

	: (then)   nest @ 0 do " +" $+ loop  " then" $+ ;

	: if
		nest ++
		" vmif " <$ (then) $> output ;

	: -if
		nest ++
		" vmmif " <$ (then) $> output ;


	: then
		nest @ 0= abort" Control structures unbalanced"
		" " <$ (then) $> output
		nest -- ;


\	: else
\		nest @ 0= abort" Control structures unbalanced"
\		" " <$ (then) $> output
\		;


\ simple variables.
	: var   "    " <$ bl parse $+ " : .db 0" $> output ;
	: dvar   "    " <$ bl parse $+ " : .dw 0" $> output ;
	: dsb   "    " <$ bl parse $+ " : .dsb $" $+ hex (.) decimal $+ $> output ;


: a:   alit dw ;

also forth definitions
	: ]  bytecode +order ;
previous definitions
	: [  bytecode -order ;



	: ;   (;)  " " output ;
	aka (:) :

	aka (#) #

	prim or
	prim xor
	prim andd
	aka fetch @
	aka store !
	aka plusstore +!
	aka plus +
	aka sbtrkt -
\	aka or or
\	aka xor xor
	aka andd and
	aka vpstore vp!
	aka vstore v!
	aka oneplus 1+
	aka oneminus 1-
	aka twodiv 2/
	aka twomul 2*
	aka fetchplus @+
	aka storeplus !+
	aka fetcha @a
	aka storea !a
	aka zless 0<
	aka less <
	aka zgreater 0>
	aka greater >
	aka uless u<
	aka ugreater u>
	prim dup
	prim drop
	prim over
	prim swap
	prim nip
	prim plusfetch
	aka plusfetch +@
	prim metaspr
	prim plusa
	aka plusa +a
	aka equals =
	prim ffetch
\	prim fplus
	prim fplusstore
	aka ffetch f@
	aka fplusstore f+!
\	aka fplus f+



only forth definitions


\ rules for literals and addressing
\  # can be used for numbers (hex or decimal is fine, but it gets spat out as hex)
\  w: and b: can be used to spit out strings as literals (so we can access variables etc)

\ dir

\ :noname

" script.s"  w/o create-file throw to #1

' file-output is output

bytecode +order
" script.f" included
bytecode -order
\ " asdfasdf " type
#1 close-file throw


\ ; catch

" compile.bat" >SHELL
